package com.zenika.zentracker.hibernate.sql;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.hibernate.Interceptor;

import com.zenika.zentracker.hibernate.jdbc.SQLSniffer;

/**
 * Proxy used by the ZenTracker tool to monitor the execution time of a <tt>PreparedStatement</tt>.
 * 
 * Only the methods executing the query are redefined from the <tt>DefaultPreparedStatementProxy</tt>
 * 
 * @see DefaultPreparedStatementProxy
 * @author Zenika
 * 
 */
public class ZenTrackerPreparedStatementProxy extends DefaultPreparedStatementProxy {

    /**
     * @param ps The real PreparedStatement. Will be the target.
     * @param interceptor The ZenTracker Interceptor.
     * @param sql The SQL query String.
     */
    public ZenTrackerPreparedStatementProxy(PreparedStatement ps, Interceptor interceptor, String sql) {
        super(ps, interceptor, sql);
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.zenika.zentracker.hibernate.sql.DefaultPreparedStatementProxy#executeQuery()
     */
    public ResultSet executeQuery() throws SQLException {
        long start = System.currentTimeMillis();
        ResultSet rs = super.executeQuery();
        logQueryExecutionTime(System.currentTimeMillis() - start);
        return rs;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.zenika.zentracker.hibernate.sql.DefaultPreparedStatementProxy#executeBatch()
     */
    public int[] executeBatch() throws SQLException {
        long start = System.currentTimeMillis();
        int[] result = super.executeBatch();
        logQueryExecutionTime(System.currentTimeMillis() - start);
        return result;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.zenika.zentracker.hibernate.sql.DefaultPreparedStatementProxy#execute()
     */
    public boolean execute() throws SQLException {
        long start = System.currentTimeMillis();
        boolean result = super.execute();
        logQueryExecutionTime(System.currentTimeMillis() - start);
        return result;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.zenika.zentracker.hibernate.sql.DefaultPreparedStatementProxy#executeUpdate()
     */
    public int executeUpdate() throws SQLException {
        long start = System.currentTimeMillis();
        int result = super.executeUpdate();
        logQueryExecutionTime(System.currentTimeMillis() - start);
        return result;

    }

    /*
     * (non-Javadoc)
     * 
     * @see java.sql.Statement#executeUpdate(java.lang.String)
     */
    public int executeUpdate(String sql) throws SQLException {
        // Used by Hibernate to create temporary tables when needed.
        long start = System.currentTimeMillis();
        int result = super.executeUpdate(sql);
        logQueryExecutionTime(System.currentTimeMillis() - start);
        return result;
    }

    /**
     * @param executionTime
     */
    private void logQueryExecutionTime(long executionTime) {
        if (interceptor != null) {
            SQLSniffer.getInstance().addSQLExecution(interceptor, query, executionTime);
        }
    }

}
